#include "screencaptureview.h"
#include "libs/controls/msgutils.h"
#include "libs/controls/toastlabel.h"
#include "libs/core/model/model.h"
#include "libs/core/model/recordmodel.h"
#include "screenlistmodel.h"
#include "services/yingceservice.h"
#include "usersettings.h"
#include "utils/utils.h"
#include "windowlistmodel.h"
#include "yingce.h"
#include <QApplication>
#include <QAudioBuffer>
#include <QAudioDevice>
#include <QCheckBox>
#include <QComboBox>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QFileDialog>
#include <QFormLayout>
#include <QIcon>
#include <QLabel>
#include <QListView>
#include <QMediaCaptureSession>
#include <QMediaDevices>
#include <QMediaFormat>
#include <QPushButton>
#include <QResizeEvent>
#include <QScreen>
#include <QShortcut>
#include <QStackedLayout>
#include <QStandardPaths>
#include <QTimer>
#include <QToolButton>
#include <QVideoWidget>

// 实现倒计时对话框，使用更符合设计规范的颜色
CountdownDialog::CountdownDialog(QWidget* parent) : QDialog(parent, Qt::FramelessWindowHint)
{
    setAttribute(Qt::WA_TranslucentBackground);

    // 使用垂直布局
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->setContentsMargins(20, 20, 20, 20);

    // 创建倒计时标签
    countdown_label_ = new QLabel(this);
    countdown_label_->setAlignment(Qt::AlignCenter);
    layout->addWidget(countdown_label_);

    resize(300, 200);
}

void CountdownDialog::setCountdown(int seconds)
{
    countdown_label_->setText(QString::number(seconds));

    // 根据倒计时数字更改颜色
    if (seconds == 1) {
        // 最后一秒使用错误色
        countdown_label_->setStyleSheet(
                "QLabel { font-size: 120px; font-weight: 600; color: #EA4335; }"); // 错误色
    } else if (seconds == 2) {
        // 第二秒使用警告色
        countdown_label_->setStyleSheet(
                "QLabel { font-size: 120px; font-weight: 600; color: #FBBC04; }"); // 警告色
    } else {
        // 其他秒数使用普通白色
        countdown_label_->setStyleSheet(
                "QLabel { font-size: 120px; font-weight: 600; color: #FFFFFF; }");
    }
}

ScreenCaptureView::ScreenCaptureView(yc::Extension* extension, QWidget* parent)
    : yc::ExtensionView(extension, parent),
      capture_session_(new QMediaCaptureSession(this)),
      screen_capture_(new QScreenCapture(this)),
      window_capture_(new QWindowCapture(this)),
      audio_input_(new QAudioInput(this)),
      media_recorder_(new QMediaRecorder(this)),
      countdown_dialog_(nullptr)
{
    setupUi();
    refreshAudioInputsList();
    updateUi();
}

ScreenCaptureView::~ScreenCaptureView()
{
    if (recording_) {
        media_recorder_->stop();
    }
}

void ScreenCaptureView::setupUi()
{
    // Get lists of screens and windows:
    screen_list_model_ = new ScreenListModel(this);
    window_list_model_ = new WindowListModel(this);

    QHBoxLayout* hl = new QHBoxLayout(this);
    hl->setContentsMargins(0, 0, 0, 0);
    hl->setSpacing(8);

    QVBoxLayout* vl = new QVBoxLayout;
    vl->setContentsMargins(0, 0, 0, 0);
    vl->setSpacing(4);
    hl->addLayout(vl);

    QLabel* source_label = new QLabel(tr("Select source(screen or window) to capture"), this);
    source_label->setObjectName("source_label");
    vl->addWidget(source_label);

    // 屏幕
    QLabel* screen_label = new QLabel(tr("Screens:"), this);
    screen_label->setObjectName("screen_label");
    vl->addWidget(screen_label);

    screen_list_view_ = new QListView(this);
    screen_list_view_->setObjectName("screen_list");
    screen_list_view_->setModel(screen_list_model_);
    vl->addWidget(screen_list_view_);

    // 窗口
    QHBoxLayout* win_layout = new QHBoxLayout;
    win_layout->setContentsMargins(0, 0, 0, 0);
    win_layout->setSpacing(0);
    vl->addLayout(win_layout);

    QLabel* window_label = new QLabel(tr("Windows:"), this);
    screen_label->setObjectName("screen_label");
    win_layout->addWidget(window_label, 1);

    auto update_action = new QAction(tr("Update Windows List"), this);
    QIcon update_icon;
    update_icon.addPixmap(QPixmap(":/images/refresh.png"), QIcon::Normal, QIcon::Off);
    update_icon.addPixmap(QPixmap(":/images/refresh-hover.png"), QIcon::Active, QIcon::Off);
    update_action->setIcon(update_icon);
    connect(update_action, &QAction::triggered, window_list_model_, &WindowListModel::populate);

    QToolButton* refresh_button = new QToolButton(this);
    refresh_button->setDefaultAction(update_action);
    refresh_button->setAutoRaise(true);
    win_layout->addWidget(refresh_button);

    window_list_view_ = new QListView(this);
    window_list_view_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
    window_list_view_->setModel(window_list_model_);
    vl->addWidget(window_list_view_, 1);

    window_list_view_->addAction(update_action);
    window_list_view_->setContextMenuPolicy(Qt::ActionsContextMenu);

    // 音频捕获设置
    QLabel* audio_label = new QLabel(tr("Audio Settings"), this);
    audio_label->setObjectName("audio_label");
    vl->addWidget(audio_label);

    QFormLayout* audio_layout = new QFormLayout;
    audio_layout->setContentsMargins(0, 0, 0, 0);
    audio_layout->setSpacing(4);
    vl->addLayout(audio_layout);

    capture_audio_checkbox_ = new QCheckBox(tr("Capture System Audio"), this);
    capture_audio_checkbox_->setChecked(true);
    audio_layout->addRow(capture_audio_checkbox_);

    audio_source_combo_ = new QComboBox(this);
    audio_layout->addRow(tr("Audio Source:"), audio_source_combo_);

    // 预览区域
    QVBoxLayout* preview_layout = new QVBoxLayout;
    preview_layout->setContentsMargins(0, 0, 0, 0);
    preview_layout->setSpacing(4);
    hl->addLayout(preview_layout, 1);

    // 预览比例控制
    QHBoxLayout* preview_controls = new QHBoxLayout();
    preview_controls->setContentsMargins(0, 0, 0, 0);
    preview_controls->setSpacing(4);
    preview_layout->addLayout(preview_controls);

    QLabel* aspect_ratio_label = new QLabel(tr("Aspect ratio:"), this);
    preview_controls->addWidget(aspect_ratio_label);

    preview_aspect_ratio_combo_ = new QComboBox(this);
    preview_aspect_ratio_combo_->addItem(tr("Stretch to fit"));
    preview_aspect_ratio_combo_->addItem(tr("Maintain aspect ratio"));
    preview_aspect_ratio_combo_->setCurrentIndex(
            UserSettings::instance().screenCaptureSettings().aspect_ratio_index);
    preview_controls->addWidget(preview_aspect_ratio_combo_);

    // 录制信息显示
    recording_info_label_ = new QLabel(tr("Ready to record"), this);
    recording_info_label_->setObjectName("info_label");
    recording_info_label_->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    preview_controls->addWidget(recording_info_label_, 1);

    start_button_ = new QPushButton(tr("Start Recording"), this);
    preview_controls->addWidget(start_button_);
    stop_button_ = new QPushButton(tr("Stop Recording"), this);
    preview_controls->addWidget(stop_button_);
    pause_resume_button_ = new QPushButton(tr("Pause"), this);
    preview_controls->addWidget(pause_resume_button_);
    open_location_button_ = new QPushButton(tr("Open Location"), this);
    open_location_button_->setEnabled(false);
    preview_controls->addWidget(open_location_button_);

    preview_widget_ = new QVideoWidget(this);
    preview_layout->addWidget(preview_widget_, 1);

    // 初始化定时器
    info_update_timer_ = new QTimer(this);
    info_update_timer_->setInterval(1000); // 1秒更新一次

    // 倒计时定时器
    countdown_timer_ = new QTimer(this);
    countdown_timer_->setInterval(1000);
    countdown_timer_->setSingleShot(false);

    // 设置捕获会话
    capture_session_->setScreenCapture(screen_capture_);
    capture_session_->setWindowCapture(window_capture_);
    capture_session_->setVideoOutput(preview_widget_);
    capture_session_->setRecorder(media_recorder_);
    capture_session_->setAudioInput(audio_input_);

    connect(screen_list_view_->selectionModel(), &QItemSelectionModel::selectionChanged, this,
            &ScreenCaptureView::onCurrentScreenSelectionChanged);
    connect(window_list_view_->selectionModel(), &QItemSelectionModel::selectionChanged, this,
            &ScreenCaptureView::onCurrentWindowSelectionChanged);

    // 定时器连接
    connect(info_update_timer_, &QTimer::timeout, this, &ScreenCaptureView::updateRecordingInfo);

    // 控制按钮
    connect(start_button_, &QPushButton::clicked, this, &ScreenCaptureView::startCountdown);
    connect(stop_button_, &QPushButton::clicked, this, &ScreenCaptureView::stopRecording);
    connect(pause_resume_button_, &QPushButton::clicked, this, [this]() {
        if (media_recorder_->recorderState() == QMediaRecorder::RecordingState)
            pauseRecording();
        else
            resumeRecording();
    });
    connect(open_location_button_, &QPushButton::clicked, this,
            [this] { utils::showFileInFolder(media_recorder_->actualLocation().toLocalFile()); });

    // 错误处理
    connect(media_recorder_, &QMediaRecorder::errorOccurred, this,
            &ScreenCaptureView::onCaptureError);
    connect(media_recorder_, &QMediaRecorder::recorderStateChanged, this,
            &ScreenCaptureView::onRecorderStateChanged);
    connect(screen_capture_, &QScreenCapture::errorOccurred, this,
            &ScreenCaptureView::onScreenCaptureError);
    connect(window_capture_, &QWindowCapture::errorOccurred, this,
            &ScreenCaptureView::onWindowCaptureError);

    // 设置预览比例
    connect(preview_aspect_ratio_combo_, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
            [this](int index) {
                applyAspectRatio(index);
                // 保存设置
                ScreenCaptureSettings scs { UserSettings::instance().screenCaptureSettings() };
                scs.aspect_ratio_index = index;
                UserSettings::instance().setScreenCaptureSettings(scs);
                UserSettings::instance().save();
            });

    // 倒计时与音频电平监控连接
    connect(countdown_timer_, &QTimer::timeout, this, &ScreenCaptureView::updateCountdown);

    // 键盘快捷键
    start_shortcut_ = new QShortcut(QKeySequence("Ctrl+R"), this);
    stop_shortcut_ = new QShortcut(QKeySequence("Ctrl+S"), this);
    pause_resume_shortcut_ = new QShortcut(QKeySequence("Ctrl+P"), this);

    connect(start_shortcut_, &QShortcut::activated, this, &ScreenCaptureView::startRecording);
    connect(stop_shortcut_, &QShortcut::activated, this, &ScreenCaptureView::stopRecording);
    connect(pause_resume_shortcut_, &QShortcut::activated, this, [this]() {
        if (media_recorder_->recorderState() == QMediaRecorder::RecordingState)
            pauseRecording();
        else
            resumeRecording();
    });

    // 应用默认的预览比例
    applyAspectRatio(1);

    updateActive(SourceType::Screen, true);
}

void ScreenCaptureView::onCurrentScreenSelectionChanged(QItemSelection selection)
{
    if (auto indexes = selection.indexes(); !indexes.empty()) {
        screen_capture_->setScreen(screen_list_model_->screen(indexes.front()));
        updateActive(SourceType::Screen, true);

        window_list_view_->clearSelection();
    } else {
        screen_capture_->setActive(false);
        screen_capture_->setScreen(nullptr);
    }
}

void ScreenCaptureView::onCurrentWindowSelectionChanged(QItemSelection selection)
{
    if (auto indexes = selection.indexes(); !indexes.empty()) {
        auto window = window_list_model_->window(indexes.front());
        if (!window.isValid()) {
            const auto ret = yc::msgutils::msgBox(
                    this, tr("Invalid window"),
                    tr("The window is no longer valid. Update the list of windows?"),
                    QMessageBox::Yes | QMessageBox::No);
            if (ret == QMessageBox::Yes) {
                updateActive(SourceType::Window, false);

                window_list_view_->clearSelection();
                window_list_model_->populate();
                return;
            }
        }

        window_capture_->setWindow(window);
        updateActive(SourceType::Window, window.isValid());

        screen_list_view_->clearSelection();
    } else {
        window_capture_->setActive(false);
        window_capture_->setWindow({});
    }
}

void ScreenCaptureView::updateActive(ScreenCaptureView::SourceType source_type, bool active)
{
    source_type_ = source_type;
    screen_capture_->setActive(active && source_type == SourceType::Screen);
    window_capture_->setActive(active && source_type == SourceType::Window);
}

void ScreenCaptureView::refreshAudioInputsList()
{
    audio_source_combo_->clear();

    const auto audio_inputs = QMediaDevices::audioInputs();
    for (const QAudioDevice& device : audio_inputs) {
        audio_source_combo_->addItem(device.description(), QVariant::fromValue(device));
    }

    if (audio_source_combo_->count() > 0) {
        // 设置默认音频输入设备
        audio_input_->setDevice(qvariant_cast<QAudioDevice>(audio_source_combo_->itemData(0)));
    }
}

void ScreenCaptureView::startRecording()
{
    if (recording_)
        return;

    // 开始倒计时，倒计时结束后会自动调用doStartRecording
    startCountdown();
}

void ScreenCaptureView::doStartRecording()
{
    if (recording_)
        return;

    const auto& settings = UserSettings::instance().screenCaptureSettings();

    // 设置音频输入
    if (!capture_audio_checkbox_->isChecked()) {
        capture_session_->setAudioInput(nullptr); // 禁用音频捕获
    } else {
        // 设置选择的音频设备
        int audio_index = audio_source_combo_->currentIndex();
        if (audio_index >= 0) {
            audio_input_->setDevice(
                    qvariant_cast<QAudioDevice>(audio_source_combo_->itemData(audio_index)));
            capture_session_->setAudioInput(audio_input_);
        }
    }

    // 设置媒体输出
    const QString filename = QDir { settings.save_dir }.absoluteFilePath(
            QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss") + ".mp4");

    QMediaFormat format;
    format.setFileFormat(QMediaFormat::FileFormat::MPEG4);
    format.setVideoCodec(QMediaFormat::VideoCodec::H264);
    if (capture_audio_checkbox_->isChecked()) {
        format.setAudioCodec(QMediaFormat::AudioCodec::AAC);

        // 设置音频采样率
        media_recorder_->setAudioSampleRate(settings.audio.sample_rate);

        // 设置音频比特率
        media_recorder_->setAudioBitRate(settings.audio.bitrate);

        // 设置音频通道数
        media_recorder_->setAudioChannelCount(settings.audio.channels);
    }
    media_recorder_->setMediaFormat(format);
    media_recorder_->setOutputLocation(QUrl::fromLocalFile(filename));

    // 应用视频比特率设置
    media_recorder_->setVideoBitRate(settings.video.bitrate);

    // 应用分辨率设置
    QString resolutionOption = settings.video.resolution;
    if (resolutionOption != "original") {
        QSize targetResolution;
        if (resolutionOption == "1080p") {
            targetResolution = QSize(1920, 1080);
        } else if (resolutionOption == "720p") {
            targetResolution = QSize(1280, 720);
        } else if (resolutionOption == "480p") {
            targetResolution = QSize(854, 480);
        }

        if (targetResolution.isValid()) {
            media_recorder_->setVideoResolution(targetResolution);
        }
    }

    // 应用帧率设置
    media_recorder_->setVideoFrameRate(settings.video.frame_rate);

    // 使用设置的值而不是固定的质量预设
    // media_recorder_->setQuality(QMediaRecorder::HighQuality);

    // 开始录制
    media_recorder_->record();
    recording_ = true;
    recording_start_time_ = QDateTime::currentMSecsSinceEpoch();
    info_update_timer_->start();
    recording_info_label_->setText("");

    updateUi();
}

void ScreenCaptureView::stopRecording()
{
    if (!recording_)
        return;

    const auto url = media_recorder_->actualLocation();
    const qint64 duration = media_recorder_->duration();

    media_recorder_->stop();
    recording_ = false;
    info_update_timer_->stop();
    open_location_button_->setEnabled(url.isValid());

    // 保存录制记录
    if (url.isValid() && duration > 0) {
        yc::RecordInfo ri;
        ri.presenter = 0;
        ri.live = 0;
        ri.duration = duration;
        ri.url = url.fileName();
        YingCeService::instance()->addRecord(
                ri,
                yc::ResponseHandler(
                        this, [](const yc::Request& request, const yc::Response& response) {
                            Q_UNUSED(request)
                            if (response.status() == yc::OK_CODE) {
                                const yc::RecordInfo ri { response.data().toObject() };
                                auto rm = YingCe::instance()->model()->recordModel();
                                if (rm->hasPresenterTotalCount(ri.presenter)) {
                                    int count = rm->presenterTotalCount(ri.presenter) + 1;
                                    rm->setPresenterTotalCount(ri.presenter, count);
                                    YingCe::instance()->model()->recordModel()->add(ri);
                                }
                            } else {
                                qDebug() << response.status() << response.msg();
                            }
                        }));
    }

    updateUi();
}

void ScreenCaptureView::pauseRecording()
{
    if (!recording_ || media_recorder_->recorderState() != QMediaRecorder::RecordingState)
        return;

    media_recorder_->pause();
    pause_resume_button_->setText(tr("Resume"));

    updateUi();
}

void ScreenCaptureView::resumeRecording()
{
    if (!recording_ || media_recorder_->recorderState() != QMediaRecorder::PausedState)
        return;

    media_recorder_->record();
    pause_resume_button_->setText(tr("Pause"));

    updateUi();
}

void ScreenCaptureView::updateUi()
{
    bool recording = recording_;
    bool paused = recording && media_recorder_->recorderState() == QMediaRecorder::PausedState;

    // 更新按钮状态
    start_button_->setEnabled(!recording);
    stop_button_->setEnabled(recording);
    pause_resume_button_->setEnabled(recording);
    pause_resume_button_->setText(paused ? tr("Resume") : tr("Pause"));
    open_location_button_->setEnabled(
            !recording && QFileInfo::exists(media_recorder_->actualLocation().toLocalFile()));

    // 更新输入控件
    screen_list_view_->setEnabled(!recording);
    window_list_view_->setEnabled(!recording);
    capture_audio_checkbox_->setEnabled(!recording);
    audio_source_combo_->setEnabled(!recording);
}

void ScreenCaptureView::onCaptureError(QMediaRecorder::Error error, const QString& errorString)
{
    yc::ToastLabel::showMessage(tr("An error occurred: %1, %2").arg(error).arg(errorString), this,
                                6000);

    if (recording_) {
        stopRecording();
    }
}

void ScreenCaptureView::onScreenCaptureError(QScreenCapture::Error error,
                                             const QString& errorString)
{
    yc::ToastLabel::showMessage(tr("An error occurred: %1, %2").arg(error).arg(errorString), this,
                                6000);

    if (recording_) {
        stopRecording();

        // 重置UI和状态
        recording_info_label_->clear();
    }
}

void ScreenCaptureView::onWindowCaptureError(QWindowCapture::Error error,
                                             const QString& errorString)
{
    yc::ToastLabel::showMessage(tr("An error occurred: %1, %2").arg(error).arg(errorString), this,
                                6000);

    if (recording_) {
        stopRecording();
    }
}

void ScreenCaptureView::onRecorderStateChanged(QMediaRecorder::RecorderState state)
{
    if (state == QMediaRecorder::StoppedState) {
        recording_ = false;
        updateUi();
    }
}

void ScreenCaptureView::updateRecordingInfo()
{
    if (!recording_)
        return;

    const auto& settings = UserSettings::instance().screenCaptureSettings();

    qint64 elapsed = QDateTime::currentMSecsSinceEpoch() - recording_start_time_;
    QString timeInfo = tr("Recording time: %1").arg(formatTime(elapsed));

    // 计算文件大小预估
    double videoBitrateInMB = settings.video.bitrate / 8.0 / 1024.0 / 1024.0;
    double audioBitrateInMB = 0;
    if (capture_audio_checkbox_->isChecked()) {
        audioBitrateInMB = settings.audio.bitrate / 8.0 / 1024.0 / 1024.0;
    }

    double totalBitrateMBs = videoBitrateInMB + audioBitrateInMB;
    double estimatedSize = totalBitrateMBs * (elapsed / 1000.0);

    QString sizeInfo = tr("Estimated file size: %1 MB").arg(QString::number(estimatedSize, 'f', 2));
    recording_info_label_->setText(timeInfo + "; " + sizeInfo);
}

QString ScreenCaptureView::formatTime(qint64 milliseconds)
{
    int seconds = (milliseconds / 1000) % 60;
    int minutes = (milliseconds / (1000 * 60)) % 60;
    int hours = (milliseconds / (1000 * 60 * 60));

    return QString("%1:%2:%3")
            .arg(hours, 2, 10, QChar('0'))
            .arg(minutes, 2, 10, QChar('0'))
            .arg(seconds, 2, 10, QChar('0'));
}

// 应用预览比例函数
void ScreenCaptureView::applyAspectRatio(int index)
{
    if (index == 0) {
        preview_widget_->setAspectRatioMode(Qt::IgnoreAspectRatio);
    } else {
        preview_widget_->setAspectRatioMode(Qt::KeepAspectRatio);
    }
}

// 开始倒计时函数
void ScreenCaptureView::startCountdown()
{
    if (recording_)
        return;

    // 创建并显示倒计时对话框
    if (!countdown_dialog_) {
        countdown_dialog_ = new CountdownDialog(this);
        // 添加取消按钮或关闭事件处理
        connect(countdown_dialog_, &CountdownDialog::rejected, this, [this]() {
            countdown_timer_->stop();

            // 重新启用控制按钮
            start_button_->setEnabled(true);
            pause_resume_button_->setEnabled(true);
            stop_button_->setEnabled(true);
        });
    }

    countdown_seconds_ = 3; // 重置为3秒
    countdown_dialog_->setCountdown(countdown_seconds_);

    // 居中显示在应用窗口
    const QPoint dlg_pos = this->geometry().center() - QPoint(150, 100); // 对话框大小的一半
    countdown_dialog_->move(mapToGlobal(dlg_pos));

    countdown_dialog_->show();
    countdown_timer_->start();

    // 在倒计时过程中禁用控制按钮
    start_button_->setEnabled(false);
    pause_resume_button_->setEnabled(false);
    stop_button_->setEnabled(false);
}

void ScreenCaptureView::updateCountdown()
{
    countdown_seconds_--;

    if (countdown_seconds_ > 0) {
        countdown_dialog_->setCountdown(countdown_seconds_);
    } else {
        countdown_timer_->stop();
        countdown_dialog_->hide();

        // 重新启用控制按钮
        start_button_->setEnabled(true);
        pause_resume_button_->setEnabled(true);
        stop_button_->setEnabled(true);

        // 开始录制
        doStartRecording();
    }
}

void ScreenCaptureView::resizeEvent(QResizeEvent* event)
{
    QWidget::resizeEvent(event);

    // 如果倒计时标签可见，则更新其位置
    if (countdown_dialog_ && countdown_dialog_->isVisible()) {
        countdown_dialog_->move(this->rect().center() - QPoint(150, 100));
    }
}

void ScreenCaptureView::showEvent(QShowEvent* event)
{
    QWidget::showEvent(event);
    if (!recording_) {
        if (source_type_ == SourceType::Screen) {
            if (screen_capture_->screen()) {
                screen_capture_->setActive(true);
            }
        } else if (source_type_ == SourceType::Window) {
            if (window_capture_->window().isValid()) {
                window_capture_->setActive(true);
            }
        }
    }
}

void ScreenCaptureView::hideEvent(QHideEvent* event)
{
    QWidget::hideEvent(event);
    if (!recording_) {
        if (source_type_ == SourceType::Screen) {
            screen_capture_->setActive(false);
        } else if (source_type_ == SourceType::Window) {
            window_capture_->setActive(false);
        }
    }
}
